<!--
 * @Author       : Hejh(3010733382@qq.com)
 * @Version      : V1.0
 * @Date         : 2024-01-29 20:04:48
 * @Description  : 操作日志管理
-->
<template>
  <div class="bg-lightColor log-con p-3 rounded">
    <n-grid x-gap="12" :cols="1" class="mb-2">
      <n-gi class="flex">
        <time-select @time-change="handleTimeChange"></time-select>
        <UserSelect
          class="!w-[300px] ml-2"
          :multiple="false"
          @change-value="handleUserChange"
        ></UserSelect>
        <n-cascader
          size="small"
          class="!w-[200px] ml-2"
          :value="logType"
          placeholder="选择内容"
          :expand-trigger="'click'"
          :options="typeOptions"
          :check-strategy="'child'"
          :show-path="false"
          :filterable="true"
          @update:value="handleUpdateValue"
          :renderLabel="renderLabel"
        />
        <n-button
          class="ml-4"
          size="small"
          @click="exportSorterAndFilterCsv"
          type="tertiary"
        >
          导出
        </n-button>
      </n-gi>
    </n-grid>
    <wp-data-table
      v-loading="loading"
      :data="data"
      :checked-row-keys="checkedRowKeys"
      :columns="columns"
      @page-change="handlePageChange"
      @select-change="handleSelectChange"
      :pages="pageResultInfo.pages"
      :total="pageResultInfo.total"
      @sort-change="handleSorterChange"
      :is-sort="false"
      ref="logTableRef"
    >
    </wp-data-table>

    <MyDialog
      default-width="90%"
      default-height="90%"
      v-if="dialogs.explorer"
      @close="dialogs.explorer = false"
    >
      <template #title>
        <div class="flex items-center text-[#555] text-[13px]">个人空间</div>
      </template>
      <Explorer></Explorer>
    </MyDialog>
  </div>
</template>

<script setup lang="ts">
import dayjs from 'dayjs'
import { NTooltip, type DataTableColumns } from 'naive-ui'
import useUserStore from '@/stores/modules/user'
import { getLogByPage } from '@/api/log'
import type { LogReq, LogRowData } from '@/types/log'
import { getLogTypeName, logTypeArr } from '@/constants/log'
import { formatTime } from '@/utils/index'
import {
  renderUserAvator,
  renderLogExport,
  renderIp,
  renderDropLabel,
  renderOs
} from '@/utils/commonBusiness'
import { getStartAndEndTime } from '@/utils/index'
import DisableUserPic from '@/assets/images/default-avata-disable.jpg'
import WpDataTable from '@/components/WpDataTable/index.vue'
import TimeSelect from './components/TimeSelect.vue'
import type { IndexObj } from '@/types/commom'
import { events } from '@/utils/bus'
import { navTypeList } from '@/constants/explorer'
import Explorer from '@/views/User/Explorer/index.vue'

const userStore = useUserStore()

const dialogs = reactive({
  explorer: false
})

const data = ref<LogRowData[]>([])
const pageInfo = reactive<LogReq>({
  page: 1,
  pageSize: 50,
  type: undefined,
  userId: undefined,
  startTime:
    getStartAndEndTime(0).startTime!.format('YYYY-MM-DD HH:mm:ss') || undefined,
  endTime:
    getStartAndEndTime(0).endTime!.format('YYYY-MM-DD HH:mm:ss') || undefined
})

const logType = ref('all')
const typeOptions = [
  {
    label: '全部',
    value: 'all',
    myIcon: 'quanbufenlei'
  },
  {
    label: '文件操作',
    value: 'source',
    myIcon: 'wenjian-yuan',
    children: logTypeArr
      .filter((item) => item.group === 'source')
      .map((v) => {
        return {
          label: v.name,
          value: v.type,
          myIcon: v.icon
        }
      })
  },
  {
    label: '用户配置',
    value: 'user',
    myIcon: 'yonghu2',
    children: logTypeArr
      .filter((item) => item.group === 'user')
      .map((v) => {
        return {
          label: v.name,
          value: v.type,
          myIcon: v.icon
        }
      })
  },
  {
    label: '后台管理',
    value: 'backend',
    myIcon: 'houtaiguanli',
    children: logTypeArr
      .filter((item) => item.group === 'backend')
      .map((v) => {
        return {
          label: v.name,
          value: v.type,
          myIcon: v.icon
        }
      })
  }
]

const handleUpdateValue = (value: string) => {
  logType.value = value
  pageInfo.type = value === 'all' ? undefined : value
  loadLogs()
}

const pageResultInfo = reactive({
  pages: 0,
  total: 0
})
const loading = ref(false)

const renderLabel = (option: any) => {
  return renderDropLabel(option.myIcon, option.label)
}

const handleTimeChange = (time: IndexObj) => {
  pageInfo.startTime = time.startTime
  pageInfo.endTime = time.endTime
  loadLogs()
}

const handleUserChange = (value: string | string[]) => {
  if (value === '') {
    pageInfo.userId = undefined
  } else {
    pageInfo.userId = value as string
  }
  loadLogs()
}

const createColumns = (): DataTableColumns<LogRowData> => {
  return [
    {
      title: '用户',
      key: 'userInfo',
      width: 150,
      minWidth: 150,
      render: (row) => {
        if (!row.user) {
          return renderUserAvator(DisableUserPic, '已删除')
        }
        const curUsername =
          userStore.userInfo?.id === row.user?.id
            ? '我自己'
            : row.user?.username
        return renderUserAvator(
          row.user?.avator as string,
          curUsername as string
        )
      }
    },
    {
      title: '操作时间',
      key: 'createTime',
      sorter: 'default',
      width: 150,
      minWidth: 150,
      render(row) {
        return formatTime(row.createTime)
      }
    },
    {
      title: '操作',
      key: 'type',
      width: 150,
      minWidth: 150,
      render(row) {
        const log = getLogTypeName(row.type)
        return log ? renderDropLabel(log.icon, log.name) : ''
      }
    },
    {
      title: '描述',
      key: 'desc',
      width: 220,
      minWidth: 220,
      render(row) {
        return renderLogDesc(row)
      }
    },
    {
      title: '登录地址',
      key: 'ip',
      width: 120,
      minWidth: 120,
      render(row) {
        return renderIp(row.ip)
      }
    }
  ]
}

const checkedRowKeys = ref<string[]>([])

const columns = createColumns()

const logTableRef = ref()

// 导出日志
const exportSorterAndFilterCsv = () =>
  logTableRef.value!.tableRef!.downloadCsv({
    fileName: 'login-logs-' + dayjs().format('YYYY-MM-DD HH:mm:ss'),
    keepOriginalData: true
  })

// 获取日志列表
const loadLogs = () => {
  loading.value = true
  getLogByPage(pageInfo)
    .then((res) => {
      res.data.items.forEach((item) => {
        renderLogExport(item)
      })
      data.value = res.data.items
      pageResultInfo.pages = res.data.pages
      pageResultInfo.total = res.data.total
    })
    .catch(console.error)
    .finally(() => {
      loading.value = false
    })
}

const handleNodeClick = (sourceInfo: any) => {
  dialogs.explorer = true
  setTimeout(() => {
    if (+sourceInfo.isDir === 0) {
      events.emit('node-click', {
        nav: {
          key: sourceInfo.parentId,
          label: sourceInfo.filename,
          myType: navTypeList.SOURCE
        },
        sourceInfo
      })
      return
    }

    // 文件夹处理
    events.emit('node-click', {
      nav: {
        key: sourceInfo.id,
        label: sourceInfo.filename,
        myType: navTypeList.SOURCE
      }
    })
  }, 300)
}

const renderSourceBtn = (source: any, userId: any, isEllisp = true) => {
  const renderName = (source: any) => {
    if (source.parentLevel === '-1' && source.targetId === userId) {
      return '个人空间'
    }
    return source.filename
  }

  if (isEllisp) {
    return h(
      NEllipsis,
      {
        style: {
          'max-width': '80px'
        },
        tooltip: {
          raw: true,
          'content-class': 'bg-yellow-100 text-[#000] p-2',
          'arrow-class': '!bg-yellow-100'
        }
      },
      {
        default: () =>
          h(
            NButton,
            {
              type: 'primary',
              class: 'text-[13px] ',
              text: true,
              onClick(e: MouseEvent) {
                handleNodeClick(source)
              }
            },
            {
              default: () => renderName(source)
            }
          )
      }
    )
  } else {
    return h(
      'span',
      {
        class: 'mx-2'
      },
      [
        h(
          NButton,
          {
            type: 'primary',
            class: 'text-[13px] ',
            text: true,
            onClick(e: MouseEvent) {}
          },
          {
            default: () => renderName(source)
          }
        )
      ]
    )
  }
}

// 渲染日志的方法
const renderLogDesc = (log: any) => {
  if (['user.login', 'user.register'].includes(log.type)) {
    return h(
      'div',
      {
        style: {
          display: 'flex',
          alignItems: 'center'
        }
      },
      [
        renderOs(log.uaParse.os),
        h('div', {
          style: {
            width: '10px'
          }
        }),
        renderOs(log.uaParse.browser)
      ]
    )
  }

  if (['user.logout', 'user.findPwd'].includes(log.type)) {
    return '用户：' + log.username || ''
    // return ''
  }

  if (log.type === 'user.infoUpdate') {
    if (!log.update.user) {
      return ''
    } else {
      const { nickname, password, avator, email } = log.update.user
      let str = ''
      nickname && (str += `昵称：${nickname}  `)
      password && (str += `密码：${password}  `)
      avator && (str += `头像：${avator}  `)
      email && (str += `邮箱：${email}  `)
      return str
    }
  }

  if (log.type === 'dep.create') {
    if (log.add && log.add.dep) {
      const { name } = log.add.dep
      const { name: pName } = log.add.pDep
      let str = ''
      name && (str += `名称：${name}  `)
      pName && (str += `父部门：${pName}  `)
      return str
    }

    return ''
  }

  if (log.type === 'dep.update') {
    if (log.update && log.update.dep) {
      const { name } = log.update.dep
      let str = ''
      name && (str += `名称：${name}  `)
      if (log.update.pDep) {
        const { name: pName } = log.update.pDep
        pName && (str += `父部门${pName}`)
      }
      return str
    }
    return ''
  }

  if (log.type === 'dep.delete') {
    if (log.dep) {
      const { name } = log.dep
      let str = ''
      name && (str += `名称：${name}  `)
      if (log.pDep) {
        const { name: pName } = log.pDep
        pName && (str += `父部门：${pName}`)
      }
      return str
    }
    return ''
  }

  if (['system.role.create', 'doc.role.create'].includes(log.type)) {
    if (log.add && log.add.role) {
      const { name } = log.add.role
      let str = ''
      name && (str += `名称：${name}  `)
      return str
    }
    return ''
  }

  if (['system.role.update', 'doc.role.update'].includes(log.type)) {
    if (log.update && log.update.role) {
      const { name } = log.update.role
      let str = ''
      name && (str += `名称：${name}  `)
      return str
    }
    return ''
  }

  if (['system.role.delete', 'doc.role.delete'].includes(log.type)) {
    if (log && log.role) {
      const { name } = log.role
      let str = ''
      name && (str += `名称：${name}  `)
      return str
    }
    return ''
  }

  if (log.type === 'admin.user.create') {
    if (log.add && log.add.user) {
      const { username } = log.add.user
      let str = ''
      username && (str += `用户：${username}`)

      let infoStr = ''
      if (log.add.userDeps) {
        const userDeps = log.add.userDeps
        for (let i = 0; i < userDeps.length; i++) {
          infoStr += '['
          const info = userDeps[i]
          const { name } = info.dep
          const { name: roleName } = info.role
          name && (infoStr += `部门：${username}，`)
          roleName && (infoStr += `角色：${roleName}，`)
          info.sizeMax && (infoStr += `空间大小：${info.sizeMax}`)
          infoStr += ']\n'
        }
      }
      // return str
      console.log(infoStr)

      return h(
        'div',
        {
          style: {
            display: 'flex',
            alignItems: 'center'
          }
        },
        [
          str,
          h(
            NEllipsis,
            {
              style: {
                'max-width': '100px'
              },
              tooltip: {
                raw: true,
                'content-class': 'bg-yellow-100 text-[#000] p-2',
                'arrow-class': '!bg-yellow-100'
              }
            },
            { default: () => infoStr }
          )
        ]
      )
    }
    return ''
  }

  if (log.type === 'admin.user.delete') {
    if (log.delete && log.delete.user) {
      const { username } = log.delete.user
      let str = ''
      username && (str += `用户：${username}  `)
      return str
    }
    return ''
  }

  if (log.type === 'admin.user.active') {
    if (log.update && log.update.user) {
      let str = ''
      const { username, status } = log.update.user
      username && (str += `用户：${username}  `)
      status !== undefined && (str += `状态：${status ? '启用' : '禁用'}`)
      return str
    }
    return ''
  }

  if (log.type === 'admin.user.copyToDep') {
    if (log.update && log.update.user) {
      let str = ''
      const { username } = log.update.user
      username && (str += `用户：${username}  `)
      // 更新用户所在部门
      let infoStr = ''
      if (log.update.userDeps) {
        const userDeps = log.update.userDeps
        for (let i = 0; i < userDeps.length; i++) {
          //
          infoStr += '['
          const info = userDeps[i]
          const { name } = info.dep
          const { name: roleName } = info.role
          name && (infoStr += `部门：${username}，`)
          roleName && (infoStr += `角色：${roleName}，`)
          info.sizeMax && (infoStr += `空间大小：${info.sizeMax}`)
          infoStr += ']'
        }
      }
      return h(
        'div',
        {
          style: {
            display: 'flex',
            alignItems: 'center'
          }
        },
        [
          str,
          h(
            NEllipsis,
            {
              style: {
                'max-width': '100px'
              },
              tooltip: {
                raw: true,
                'content-class': 'bg-yellow-100 text-[#000] p-2',
                'arrow-class': '!bg-yellow-100'
              }
            },
            { default: () => infoStr }
          )
        ]
      )
    }
    return ''
  }

  if (log.type === 'admin.user.removeFromDep') {
    if (log.delete && log.delete.user) {
      let str = ''
      const { username } = log.delete.user
      const { name } = log.delete.dep
      username && (str += `用户：${username}  `)
      username && (str += `部门：${name}  `)
      return str
    }
    return ''
  }

  if (log.type === 'admin.user.update') {
    if (log.update && log.update.user) {
      const {
        username,
        nickname,
        roleName,
        sex,
        sizeMax,
        email,
        phone,
        password
      } = log.update.user
      let str = ''
      username && (str += `用户：${username}  `)
      nickname && (str += `昵称：${nickname}  `)
      roleName && (str += `系统角色：${roleName}  `)
      sex !== undefined && (str += `性别：${+sex === 0 ? '男' : '女'}  `)
      sizeMax && (str += `空间：${sizeMax}  `)
      email && (str += `邮箱：${email}  `)
      phone && (str += `手机号：${phone}  `)
      password && (str += `密码：${password}  `)
      // 更新用户所在部门
      let infoStr = ''
      if (log.update.user.userDeps) {
        const userDeps = log.update.user.userDeps
        for (let i = 0; i < userDeps.length; i++) {
          //
          infoStr += '['
          const info = userDeps[i]
          const { name } = info.dep
          const { name: roleName } = info.role
          name && (infoStr += `部门：${username}，`)
          roleName && (infoStr += `角色：${roleName}，`)
          info.sizeMax && (infoStr += `空间大小：${info.sizeMax}`)
          infoStr += ']'
        }
      }
      return h(
        'div',
        {
          style: {
            display: 'flex',
            alignItems: 'center'
          }
        },
        [
          h(
            NEllipsis,
            {
              style: {
                'max-width': '100px'
              },
              tooltip: {
                raw: true,
                'content-class': 'bg-yellow-100 text-[#000] p-2',
                'arrow-class': '!bg-yellow-100'
              }
            },
            { default: () => str }
          ),
          h(
            NEllipsis,
            {
              style: {
                'max-width': '100px'
              },
              tooltip: {
                raw: true,
                'content-class': 'bg-yellow-100 text-[#000] p-2',
                'arrow-class': '!bg-yellow-100'
              }
            },
            { default: () => infoStr }
          )
        ]
      )
    }
    return ''
  }

  // 文件操作日志渲染
  if (log.type === 'source.mkdir') {
    if (!log.curSource) {
      return ''
    }
    //
    return h(
      'div',
      {
        style: {
          display: 'flex',
          alignItems: 'center'
        }
      },
      [
        '在',
        renderSourceBtn(log.pSource, log.userId),
        h(
          'div',
          {
            class: 'mx-2'
          },
          '创建了'
        ),
        renderSourceBtn(log.curSource, log.userId)
      ]
    )
  }

  if (log.type === 'source.rename') {
    if (!log.curSource) {
      return ''
    }
    return h(
      'div',
      {
        style: {
          display: 'flex',
          alignItems: 'center'
        }
      },
      ['重命名了', renderSourceBtn(log.curSource, log.userId)]
    )
  }

  if (log.type === 'source.upload') {
    if (!log.curSource) {
      return ''
    }
    //
    return h(
      'div',
      {
        style: {
          display: 'flex',
          alignItems: 'center'
        }
      },
      [
        '在',
        renderSourceBtn(log.pSource, log.userId),
        h(
          'div',
          {
            class: 'mx-2'
          },
          '上传了'
        ),
        renderSourceBtn(log.curSource, log.userId)
      ]
    )
  }

  if (log.type === 'source.download.file') {
    if (!log.curSource) {
      return ''
    }
    //
    return h(
      'div',
      {
        style: {
          display: 'flex',
          alignItems: 'center'
        }
      },
      [
        '在',
        renderSourceBtn(log.pSource, log.userId),
        h(
          'div',
          {
            class: 'mx-2'
          },
          '下载了'
        ),
        renderSourceBtn(log.curSource, log.userId)
      ]
    )
  }

  if (log.type === 'source.download.dir') {
    //文件夹下载
    if (log.sources && log.sources.length) {
      return h(
        NEllipsis,
        {
          style: {
            'max-width': '240px'
          },
          tooltip: {
            raw: true,
            'content-class': 'bg-yellow-100 text-[#000] p-2',
            'arrow-class': '!bg-yellow-100'
          }
        },
        ['下载了'].concat(
          log.sources.map((item: any) =>
            renderSourceBtn(item, log.userId, false)
          )
        )
      )
    }

    return ''
  }

  if (log.type === 'source.bin') {
    //
    if (!log.curSource) {
      return ''
    }
    return h(
      'div',
      {
        style: {
          display: 'flex',
          alignItems: 'center'
        }
      },
      [
        '在',
        renderSourceBtn(log.pSource, log.userId),
        h(
          'div',
          {
            class: 'mx-2'
          },
          '将'
        ),
        renderSourceBtn(log.curSource, log.userId),
        '移到了回收站'
      ]
    )
  }

  if (log.type === 'source.delete') {
    //
    if (!log.curSource) {
      return ''
    }
    return h(
      'div',
      {
        style: {
          display: 'flex',
          alignItems: 'center'
        }
      },
      [
        '从',
        renderSourceBtn(log.pSource, log.userId),
        h(
          'div',
          {
            class: 'mx-2'
          },
          '删除了'
        ),
        renderSourceBtn(log.curSource, log.userId)
      ]
    )
  }

  if (log.type === 'source.recycle') {
    //
    if (!log.curSource) {
      return ''
    }
    return h(
      'div',
      {
        style: {
          display: 'flex',
          alignItems: 'center'
        }
      },
      ['从回收站还原：', renderSourceBtn(log.curSource, log.userId)]
    )
  }

  if (log.type === 'source.move') {
    //移动
    if (!log.curSource) {
      return ''
    }
    return h(
      'div',
      {
        style: {
          display: 'flex',
          alignItems: 'center'
        }
      },
      [
        '将',
        renderSourceBtn(log.curSource, log.userId),
        h(
          'div',
          {
            class: 'mx-2'
          },
          '从'
        ),
        renderSourceBtn(log.pSource, log.userId),
        h(
          'div',
          {
            class: 'mx-2'
          },
          '移动到'
        ),
        renderSourceBtn(log.toSource, log.userId)
      ]
    )
  }

  if (log.type === 'source.copy') {
    // 复制
    if (!log.curSource) {
      return ''
    }
    return h(
      'div',
      {
        style: {
          display: 'flex',
          alignItems: 'center'
        }
      },
      [
        '将',
        renderSourceBtn(log.curSource, log.userId),
        h(
          'div',
          {
            class: 'mx-2'
          },
          '从'
        ),
        renderSourceBtn(log.pSource, log.userId),
        h(
          'div',
          {
            class: 'mx-2'
          },
          '复制到'
        ),
        renderSourceBtn(log.toSource, log.userId)
      ]
    )
  }

  if (['source.share.extend', 'source.share.inner'].includes(log.type)) {
    if (!log.share) {
      return ''
    }
    return h(
      'div',
      {
        style: {
          display: 'flex',
          alignItems: 'center'
        }
      },
      [
        log.model === 'cancel' ? '关闭了' : '更新了',
        h(
          NEllipsis,
          {
            style: {
              'max-width': '80px'
            },
            tooltip: {
              raw: true,
              'content-class': 'bg-yellow-100 text-[#000] p-2',
              'arrow-class': '!bg-yellow-100'
            }
          },
          {
            default: () =>
              h(
                NButton,
                {
                  type: 'primary',
                  class: 'text-[13px] ',
                  text: true,
                  onClick(e: MouseEvent) {
                    handleNodeClick(log.curSource)
                  }
                },
                {
                  default: () => log.share.title
                }
              )
          }
        ),
        log.type === 'source.share.extend' ? '外链分享' : '内部协作分享'
      ]
    )
  }
}

onMounted(() => {
  loadLogs()
})

const handlePageChange = (page?: number, pageSize?: number) => {
  page && (pageInfo.page = page)
  pageSize && (pageInfo.pageSize = pageSize)
  loadLogs()
}

const handleSelectChange = (rows: string[]) => {
  checkedRowKeys.value = rows.map((item) => item)
}

const handleSorterChange = (sorter: IndexObj) => {
  if (sorter && sorter.columnKey === 'createTime') {
    if (sorter.order === 'ascend') {
      data.value = data.value.sort((v1: LogRowData, v2: LogRowData) => {
        return dayjs(v1.createTime).valueOf() - dayjs(v2.createTime).valueOf()
      })
    } else {
      data.value = data.value.sort((v1: LogRowData, v2: LogRowData) => {
        return dayjs(v2.createTime).valueOf() - dayjs(v1.createTime).valueOf()
      })
    }
  }
}
</script>

<style scoped lang="scss">
.log-con {
  font-size: 13px;

  :deep(.n-data-table-tbody .n-data-table-tr:hover .n-data-table-td) {
    background-color: #e5f3ff;

    .move {
      opacity: 0.85;
    }
  }

  :deep(.my-handle) {
    height: 28px;
    line-height: 28px;
    // height: calc(100% + 16px);
    position: relative;
    .move {
      transition: all 0.3s var(--n-bezier);
      opacity: 0;
      display: flex;
      justify-content: center;
      align-items: center;
      background-color: #d1ecfa;
      color: $primaryColor;
      position: absolute !important;
      left: -8px;
      top: -8px;
      bottom: -8px;
      width: 40px;
      // right: 0;
      cursor: move;
    }
  }
}
</style>
